package DEEPERsource.DEEPERsource.source.machinelearning.wekawrapper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import deeper.Interaction;

import machinelearning.features.FeatureBuilder;
import weka.core.Instances;

/**
 * Interaction dataset representation
 * @author tfayruzo
 *
 */
public class Dataset {
	
	//a hack to incorporate precomputed kernels into the general system
	private boolean precomputedKernel = false;
	private String fileName = "";
		
	private FeatureBuilder builder;

	private List<Interaction> source = new ArrayList<Interaction>();
	private List<String> classValues = new ArrayList<String>(); 

	public Dataset(Collection<Interaction> data, FeatureBuilder builder) {
		this.builder = builder;
		for(Interaction i : data){
			source.add(i);
		}
	}
	
	public Dataset(String fileName) {
		this.fileName = fileName;
		precomputedKernel = true;
	}
	
	public Dataset(FeatureBuilder builder) {
		this.builder = builder;
	}
	
	public Dataset(Dataset dataset){
		builder = dataset.builder;
		source = dataset.source;
	}
	
	public void addData(Collection<Interaction> data){
		source.addAll(data);
	}
	
	public void addClassValues(Collection<String> data){
		classValues.addAll(data);
	}
	
	public List<String> getClassValues(){
		return classValues;
	}
	
	public Dataset getTrainCVFold(int numFolds, int fold) {
		int numInst = source.size();
		int numInstForFold = numInst / numFolds;
		int offset;
	    if (fold < numInst % numFolds) {
	      numInstForFold++;
	      offset = fold;
	    }else
	      offset = numInst % numFolds;
	    List<Interaction> train = new ArrayList<Interaction>(numInst - numInstForFold);
	    int first = fold * (numInst / numFolds) + offset;
	    train.addAll(source.subList(0, first));
	    train.addAll(source.subList(first + numInstForFold, source.size()));
	    return new Dataset(train, builder);
	}

	public Dataset getTestCVFold(int numFolds, int fold) {
		int numInst = source.size();
		int numInstForFold = numInst / numFolds;
		int offset;
	    if (fold < numInst % numFolds) {
	      numInstForFold++;
	      offset = fold;
	    }else
	      offset = numInst % numFolds;
	    List<Interaction> test = new ArrayList<Interaction>(numInstForFold);
	    int first = fold * (numInst / numFolds) + offset;
	    test.addAll(source.subList(first,first + numInstForFold));
	    return new Dataset(test, builder);
	}

	/**
	 * Converts dataset to the Weka representation
	 * @return
	 */
	public Instances getDataset() {
		Instances dataset = builder.getInstanceStructure();
		for (Interaction i : source) {
			dataset.add(builder.getFeatureVector(i));
		}
		return dataset;
	}

	public void stratify(int numFolds) {
		Collections.sort(source);
		List<Interaction> strat = new ArrayList<Interaction>();
		int start = 0, j;
		int size = source.size();
		while (strat.size() < size) {
			j = start;
			while (j < size) {
				strat.add(source.get(j));
				j += numFolds;
			}
			start++;
		}
		source = strat;
	}
	
	public FeatureBuilder getBuilder(){
		return builder;
	}
	
	public List<Interaction> getInteractions(){
		return source;
	}
	
	public boolean isPrecomputed(){
		return precomputedKernel;
	}
	
	public String getPrecomputedKernel(){
		return fileName;
	}
}
